{*******************************************************************************
* The contents of this file are used with permission, subject to the Mozilla   *
* Public License Version 1.1 (the "License"); you may not use this file except *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.mozilla.org/MPL/                                                  *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for *
* the specific language governing rights and limitations under the License.    *
*                                                                              *
* The Original Code is distributed as part of the "mediate" product and is     *
* Copyright (C) @home media limited. All Rights Reserved.                      *
*                                                                              *
* Email: support@athomemedia.co.uk                                             *
* Web:   http://www.athomemedia.co.uk                                          *
*******************************************************************************}

unit MetaValues;

interface

uses Classes, UIObjects, MetaData, XMLHelper, AHMTypes;

{$IFDEF DESIGNER}
const
  MODIFY_CAPTION = 'Edit Value';

  // Property categories and hints for designer
  CAT_METAVALUE = 'Meta Data';
  HINT_VALUE = 'defines the value for this meta data item';
{$ENDIF}

type
  TAHMMetaValue = class(TAHMUIObject)
  private
    FValue: TAHMMemoString;
  protected
    procedure ClearProperties; override;
  public
    constructor Create(const Name: String); override;
    function RenderPreview: Boolean; override;
    function ModifyActions: Integer; override;
    function Modify(Action: Integer): Boolean; override;
    function ModifyCaption(Action: Integer): String; override;
    procedure Assign(Source: TPersistent); override;
    procedure SaveAsXML(Lines: TStrings); override;
    procedure ParseFromXML(XML: TAHMXMLHelper); override;
    procedure BuildProperties(Properties: TAHMUIPropertyList); override;
  published
    property Value: TAHMMemoString read FValue write FValue;
  end;

  TAHMMetaValueList = class(TAHMUIObjectList)
  private
  protected
  public
    constructor Create; override;
    function AddMetaValue(const InheritFrom, NewName: String): TAHMMetaValue;
    function GetMetaValue(const Name: String): TAHMMetaValue;
    procedure Apply;
    procedure ReadValues(Prefix: String; Values: TAHMMetaData);
    function Modify: Boolean; override;
  end;

implementation

uses SysUtils, ApplicationManager, Screen, MetaConsts, TagNames, XMLTags,
     {$IFDEF DESIGNER} DesignerList, DesignerPropsEdit,{$ENDIF} UniCode;


constructor TAHMMetaValueList.Create;
begin
  inherited Create;

  XMLTagName := TAG_META_INFO;
  ChildClass := TAHMMetaValue;
  FSpaceElements := False;
end;

function TAHMMetaValueList.AddMetaValue(const InheritFrom, NewName: String): TAHMMetaValue;
begin
  Result := TAHMMetaValue(Inherit(InheritFrom, NewName));
end;

function TAHMMetaValueList.GetMetaValue(const Name: String): TAHMMetaValue;
begin
  Result := TAHMMetaValue(GetObject(Name));
end;

procedure TAHMMetaValueList.Apply;
var
  Values: TAHMMetaData;
  Value: TAHMMetaValue;
  i: Integer;
begin
  // Apply stored meta data values to metadata manager
  Values := TAHMMetaData.Create;
  try
    for i := 0 to Pred(Count) do
    begin
      Value := TAHMMetaValue(Objects[i]);
      Values.AddValue(Value.Name, Value.Value);
    end;
    Values.Apply;
  finally
    Values.Free;
  end;
end;

procedure TAHMMetaValueList.ReadValues(Prefix: String; Values: TAHMMetaData);
var
  Name: String;
  Value: TAHMMetaValue;
  i: Integer;
begin
  // Append/update current values within our metadata list
  if Assigned(Values) then
    for i := 0 to Pred(Values.Count) do
    begin
      Name := Prefix + META_SEP + Values.Names[i];
      if IndexOf(Name) < 0 then AddMetaValue('', Name);

      Value := GetMetaValue(Name);
      if Assigned(Value) then Value.Value := Values.Values[i];

      // Parse any nested values recursively
      if Values.Objects[i] <> nil then
        ReadValues(Name, TAHMMetaData(Values.Objects[i]));
    end;
end;

function TAHMMetaValueList.Modify: Boolean;
begin
{$IFDEF DESIGNER}
  // Edit meta values with list dialog
  Result := TfrmObjectList.ShowList(Self, nil, nil);
{$ELSE}
  Result := False;
{$ENDIF}
end;

//----------------------------------------------------------------------------//
constructor TAHMMetaValue.Create(const Name: String);
begin
  inherited Create(Name);

  XMLTagName := TAG_META_ITEM;
  ObjectType := otMetaInfo;
  ImageIndex := Ord(otMetaInfo);
end;

procedure TAHMMetaValue.ClearProperties;
begin
  inherited;

  // Clear custom meta value properties
  FValue := '';
end;

function TAHMMetaValue.RenderPreview: Boolean;
begin
{$IFDEF DESIGNER}
  with ScreenInstance.Viewport do
  begin
    Canvas.DesignerBackground(ViewportRect);
    Canvas.TextRect(ViewportRect, nil, 'Meta Value:' + sLineBreak +
                    FValue + sLineBreak + sLineBreak + 'Result:' + sLineBreak +
                    ApplicationManagerInstance.MetaDataManager.ProcessMarkup(FValue));
  end;
{$ENDIF}
  Result := True;
end;

function TAHMMetaValue.ModifyActions: Integer;
begin
  // Supports single action to modify value
  Result := 1;
end;

function TAHMMetaValue.Modify(Action: Integer): Boolean;
begin
{$IFDEF DESIGNER}
  // Edit value with property dialog
  Result := TfrmObjectProperties.EditObject(Self, Owner);
  if Result then DoModified;
{$ELSE}
  Result := False;
{$ENDIF}
end;

function TAHMMetaValue.ModifyCaption(Action: Integer): String;
begin
{$IFDEF DESIGNER}
  Result := MODIFY_CAPTION;
{$ELSE}
  Result := '';
{$ENDIF}
end;

procedure TAHMMetaValue.Assign(Source: TPersistent);
begin
  inherited Assign(Source);

  with Source as TAHMMetaValue do
  begin
    Self.Value := Value;
  end;
end;

procedure TAHMMetaValue.SaveAsXML(Lines: TStrings);
var
  oAncs: TAHMMetaValue;
  sWork: String;
begin
  // Determine which ancestor to compare against - real or empty
  oAncs := TAHMMetaValue(ObjectToCompare);

  // We need to explicitly save comments in overridden method
  SaveXMLComments(Lines);

  // Not using BeginTag, so need to add name manually
  sWork := TGB+TAG_META_ITEM+SPC+ATTR_NAME+ATB + EncodeXML(Name);

  // Do we need to specify value?
  if (FValue <> '') and (FValue <> oAncs.Value) then
    sWork := sWork + ATN+ATTR_VALUE+ATB + EncodeXML(FValue);

  // Need to redo description and inheritance here, since not using BeginTag
  if (Description <> '') and (Description <> oAncs.Description) then
    sWork := sWork + ATN+ATTR_DESC+ATB + EncodeXML(Description);
  if (Ancestor <> nil) then
    sWork := sWork + ATN+ATTR_INHERIT+ATB + EncodeXML(Ancestor.Name);

  Lines.Add(TABS[XMLIndent + 2] + sWork + ATE);
end;

procedure TAHMMetaValue.ParseFromXML(XML: TAHMXMLHelper);
var
  sValue: String;
begin
  // Just parse meta value
  sValue := XML.GetAttribute(ATTR_VALUE);
  if sValue <> '' then Value := sValue;
end;

procedure TAHMMetaValue.BuildProperties(Properties: TAHMUIPropertyList);
begin
{$IFDEF DESIGNER}
  inherited;

  // Build custom meta value properties
  Properties.Add('Value', 'Value', CAT_METAVALUE, HINT_VALUE);
{$ENDIF}
end;

end.
